import java.io.File;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Random;
import java.util.Scanner;



public class MatrixTester
{
	static AbstractMatrix dm;
	static AbstractMatrix dm2;
	static AbstractMatrix dm10;
	
	
	/* make assertion method */
	public static void assertTrue(boolean flag){
		if (flag = true){
			return;
		}
		else
			throw new RuntimeException("assertion True fails");
	}
	
	public static void assertFalse(boolean flag){
		if (flag == false){
			return;
		}
		else
			throw new RuntimeException("assertion False fails");
	}
	/* Test the initialization process */
	public static void initTest()
	{
		dm10 = new DenseMatrix();
		dm2 = new DenseMatrix();
		dm = new SparseMatrix();
		Scanner scanner1 = null;
		Scanner scanner2 = null;
		Scanner scanner3 = null;
		
		File file = new File("../matrixFile/data.txt");
		try {
			scanner1 = new Scanner(file);
			scanner2 = new Scanner(file);
			scanner3 = new Scanner(file);
		}
		catch (Exception e){
			System.out.println("fails to scan the file: " + e);
		}
		
		dm.importData(scanner1);
		scanner1.close();
		
		dm2.importData(scanner2);
		scanner2.close();
		
		dm10.importData(scanner3);
		scanner3.close();
		
		
		System.out.println(dm);
		System.out.println(dm10);
		//throw new RuntimeException("You must implement this method!");
	}
	
	/* Basic set-get test */
	public static void setGetTest()
	{
		Random rm = new Random(System.currentTimeMillis());
		double val;
		int row;
		int col;
		int time = 200;
		
		NumberFormat fm = new DecimalFormat("#0.00");
		System.out.println("Start to test set-get method...");
		
		while(time-- > 0){
			row = rm.nextInt(dm.getRows());
			col = rm.nextInt(dm.getCols());
			val = Math.pow(-1, rm.nextInt(2)) * Double.parseDouble(fm.format((rm.nextDouble()*99)));
			
			dm.set(row, col, val);
			assertTrue(dm.get(row, col) == val);
		}	
		System.out.println("all test passed for set-get method!!");
		
		//throw new RuntimeException("You must implement this method!");
	}
	
	/* Basic matrix addition and subtraction test */
	public static void addSubTest()
	{
		System.out.println("Start to test add sub method ...");
		AbstractMatrix dm3 = new DenseMatrix();
		dm3.init(dm.getRows(), dm.getCols());
		dm3.clear();
		
		dm.add(dm2);
		assertFalse(dm.equals(dm2));
		assertTrue(dm.equals(dm));
		
		dm.sub(dm2);
		assertTrue(dm.equals(dm));
		assertFalse(dm.equals(dm2));
		
		dm.sub(dm);
		assertTrue(dm.equals(dm3));
		
		dm.add(dm2);
		assertTrue(dm.equals(dm2));
		
		System.out.println("All tests passed for add sub method!!");
		
		//System.out.println(dm);
		//System.out.println(dm2);
		
		//throw new RuntimeException("You must implement this method!");
	}
	
	/* Test equality operation */
	public static void equalsTest()
	{	System.out.println("Start to test the equal method ...");
		assertFalse(dm.equals(dm2));
		assertTrue(dm.equals(dm));
		assertTrue(dm2.equals(dm2));
		assertFalse(dm.equals(new DenseMatrix()));
		System.out.println("All tests passed for equal method!!");
		//throw new RuntimeException("You must implement this method!");
	}
	
	/* Test symmetry test operation */
	public static void symmetricTest()
	{
		AbstractMatrix dm3 = new DenseMatrix();
		dm3.init(3, 5);
		dm3.clear();
		
		System.out.println("Start to test the isSymmetric method ...");
		assertTrue(dm.isSymmetric());
		assertFalse(dm3.isSymmetric());
		System.out.println("All tests passed for the isSymmetric method!!");
		
		//throw new RuntimeException("You must implement this method!");
	}
	
	/* Test data import operation */
	public static void importTest()
	{
		throw new RuntimeException("You must implement this method!");
	}
	
	/* Stress test */
	public static void stressTest()
	{
		assertTrue(dm.checkRepresentation());
		//throw new RuntimeException("You must implement this method!");
	}
	
	public static void main(String[] args)
	{
		initTest();
		setGetTest();
		equalsTest();
		addSubTest();
		symmetricTest();
		//importTest();
		//stressTest();
	}
	
}
